﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Scanner_Project
{
    class Parser
    {
        Scanner scanner;
        Token CurrentToken = new Token();
        public Parser(string Input)
        {
            scanner = new Scanner(Input);
            CurrentToken = scanner.GetToken();
            Exp();
        }
        public Parser()
        {

        }
        public bool IsSynaxCorrect(string Text)
        {
            scanner = new Scanner(Text);
            CurrentToken = scanner.GetToken();
            bool Result = true;
            while (CurrentToken.Type != TokenType.EndFile && Result)
            {
                Result &= Prog();
            }
            Result &= (CurrentToken.Type == TokenType.EndFile);
            return Result;
        }
        public bool Match(TokenType Expected)
        {
            bool IsMatching = false;
            if (Expected == CurrentToken.Type)
            {
                CurrentToken = scanner.GetToken();
                IsMatching = true;
            }
            return IsMatching;
        }
        public bool Prog()
        {
            bool Result = StmtSeq();
            return Result;
        }
        public bool StmtSeq()
        {
            bool Result = Stmt();
            if(CurrentToken.Type != TokenType.EndFile || CurrentToken.Type != TokenType.End)
                Result &= Match(TokenType.SemiColon);
            return Result;
        }
        public bool Stmt()
        {
            bool Result=false;
            if (CurrentToken.Type == TokenType.If)
            {
                Result = IfStmt();
            }
            else if (CurrentToken.Type == TokenType.Repeat)
            {
                Result = RepeatStmt();
            }
            else if( CurrentToken.Type == TokenType.ID)
            {
                Result = AssignStmt();
            }
            else if (CurrentToken.Type == TokenType.Read)
            {
                Result = ReadStmt();
            }
            else if (CurrentToken.Type == TokenType.Write)
            {
                Result = WriteStmt();
            }
            return Result;
        }
        public bool IfStmt()
        {
            bool Result = Match(TokenType.If);
            Result &= Match(TokenType.LeftParentheses);
            Result &= Exp();
            Result &= Match(TokenType.RightParentheses);
            Result &= StmtSeq();
            if (CurrentToken.Type == TokenType.Else)
            {
                Result &= Match(TokenType.Else);
                Result &= StmtSeq();
            }
            Result &= Match(TokenType.End);
            return Result;
        }
        public bool RepeatStmt()
        {
            bool Result = Match(TokenType.Repeat);
            Result &= StmtSeq();
            Result &= Match(TokenType.Until);
            Result &= Match(TokenType.LeftParentheses);
            Result &= Exp();
            Result &= Match(TokenType.RightParentheses);
            return Result;
        }   
        public bool ReadStmt()
        {
            bool Result = Match(TokenType.Read);
            Result &= Match(TokenType.LeftParentheses);
            Result &= Match(TokenType.ID);
            Result &= Match(TokenType.RightParentheses);
            return Result;
        }
        public bool WriteStmt()
        {
            bool Result = Match(TokenType.Write);
            Result &= Match(TokenType.LeftParentheses);
            Result &= Exp();
            Result &= Match(TokenType.RightParentheses);
            return Result;
        }
        public bool AssignStmt()
        {
            bool Result = Match(TokenType.ID);
            Result &= Match(TokenType.Assign);
            Result &= Exp();
            return Result;
        }
        public bool Exp()
        {
            bool Result = SimpleExp();
            if (CurrentToken.Type == TokenType.LessThan || CurrentToken.Type == TokenType.GreatThan || CurrentToken.Type == TokenType.Equal)
            {
                Result &= Match(CurrentToken.Type);
                Result &= SimpleExp();
            }
            return Result;
        }
        public bool SimpleExp()
        {
            bool Result = Term();
            while (CurrentToken.Type == TokenType.Plus || CurrentToken.Type == TokenType.Minus)
            {
                Result &= Match(CurrentToken.Type);
                Result &= Term();
            }
            return Result;
        }
        public bool Term()
        {
            bool Result = Factor();
            while (CurrentToken.Type == TokenType.Times)
            {
                Result &= Match(TokenType.Times);
                Result &= Factor();
            }
            return Result;
        }
        public bool Factor()
        {
            bool Result=false;
            if(CurrentToken.Type == TokenType.Number)
            {
                Result = Match(TokenType.Number);
            }
            else if (CurrentToken.Type == TokenType.LeftParentheses)
            {
                Result = Match(TokenType.LeftParentheses);
                Result &= SimpleExp();
                //Result &= Exp();
                Result &= Match(TokenType.RightParentheses);
            }
            else if (CurrentToken.Type == TokenType.ID)
            {
                Result = Match(TokenType.ID);
            }
            return Result;
        }
    }

}
    